/*******************************************************************************
/
/ svideo.cpp
/
/ Creado por Roberto García Carvajal.
/
/ Incluye un gestor de menús muy simple (los menú de compras son poco
/ poco parametrizables y dejan mucho que desear, al igual que el de mapas).
/
/ La gestión de imagenes la realiza mediante un vector, para que sea más fácil
/ indizarlos.
/
/ El gestor de colisiones consta de 2 partes principalmente, un gestor que
/ las detecta en los menús y otro que lo detecta en batalla.
/
/ Documento bajo licencia GPL.
/
*******************************************************************************/

#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <iostream>
#include <fstream>
#include <vector>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_ttf.h>
#include "sentrada.h"
#include "svideo.h"
#include "sred.h"
#include "nucleo.h"
#include "gui.h"
#include "gtec.h"
#include "guni.h"
#include "svideo-m.h"
#include "recursos.h"
#include "mapa.h"
#include "tablero.h"

// Option flags. Para simplificar las opciones de la clase.
#define OF_UNIDAD_MOV   0x00000001
#define OF_NUEVO_MENS   0x00000002
#define OF_ESCRITURA    0x00000004
#define OF_MODO_MENU    0x00000008
#define OF_MINIMAPA     0x00000010
#define OF_P_COMPLETA   0x00000020
#define OF_MODO_EDICION 0x00000040
#define OF_DIBUJANDO    0x00000080
#define OF_MAPA_EDITADO 0x00000100
#define OF_FIN_BATALLA  0x00000200
#define OF_VIDA         0x00000400

// Modo de depuración.
#define _M_G_DEBUG_ 0


// Devuelve el valor absoluto de a
int absoluto(int a)
{
 if(a < 0)
  return -a;
 return a;
}

// Devuelve true si son iguales y false en caso contrario.
bool comparar(char * a,char * b)
{
 if(strlen(a) != strlen(b))
  return false;
 
 int l = strlen(a);
 
 for(int i = 0;i < l; i++)
  if(a[i] != b[i])
   return false;

 return true;
}

// Devuelve el máximo de a y b.
int max(int a,int b)
{
 if(a > b) return a; return b;
}

// Devuelve el mínimo de a y b.
int min(int a,int b)
{
 if(a > b) return b; return a;
}

// Casting de cadena a entero.
int cadenaaentero(char * cadena)
{
 for(int i = 0;cadena[i] != '\000';i++)
  if(cadena[i] > 57 || cadena[i] < 48)
   return 0;

 int resultado = 0;
 for(int i = 0;cadena[i] != '\000';i++)
 {
  resultado *=10;
  resultado += cadena[i] - 48;
 }
 return resultado;
}

// Casting de entero a cadena. ¡CUIDADO! ¡RESERVA MEMORIA!
char * enteroacadena(int n)
{
 char * c,*t;
 c = new char[7];
 t = new char[7];
 unsigned int i;
 for(i = 0;n;i++)
 {
  t[i] = n%10 + 48;
  n /= 10;
 }
 t[i] = '\000';
 for(unsigned j = 0;j < i;j++)
 {
  c[j] = t[i - j - 1];
 }
 c[i] = '\000';
 delete t;
 return c;
}

/*******************************************************************************
/
/ Constructor clase c_svideo.
/
/ Inicializa la ventana de SDL, todas las variables del subsistema de video
/ Carga todos los menús y las imágenes.
/ Inicializa las variables para el arranque inicial.
/
*******************************************************************************/

c_svideo::c_svideo()
{
 // Inicializo SDL video.
 if(SDL_Init(SDL_INIT_VIDEO) < 0)
 {
  std::cout << "SDL_Init error: " << SDL_GetError() << std::endl;
  exit(EXIT_FAILURE);
 }
 
 atexit(SDL_Quit);

 // Inicializo SDL ttf.
 if(TTF_Init())
  std::cout << "TTF_Init error: " << SDL_GetError() << std::endl;
 
 // Creo la pantalla (No pantalla completa) y escondo el cursor.
 SDL_ShowCursor(false);
 pantalla = SDL_SetVideoMode(640,480,24,SDL_HWSURFACE|SDL_DOUBLEBUF);
 

 // Cargo el menú de configuración de guis.
 fstream fconfig("config/gui.config",ios_base::in);
 {
  int nguis;
  fconfig >> nguis;
  gui = new c_objeto_gui**[nguis];
  nogui = new unsigned int[nguis];
  // Cargo cada una de las guis.
  for(int i = 0;i < nguis;i++)
  {
   char nfgui[256];
   fconfig >> nfgui;
   fstream fgui(nfgui,ios_base::in);
   int nobj;	
   fgui >> nobj;
   nogui[i] = nobj;
   fgui.ignore();
   gui[i] = new c_objeto_gui*[nobj];
   if(_M_G_DEBUG_)
    cout << "[svideo]-> Cargando gui '" << nfgui << "' con " << nobj << " objetos." << endl;
   // Cargo los objetos de la gui.
   for(int j = 0;j < nobj;j++)
   {
    char tipo[10],* btexto = new char[100];
    int id,x,y,im;
    unsigned int nmsg;
    c_sv_mensaje msg;
    fgui.getline(tipo,100,':');
    if(comparar("boton",tipo)) // Botones.
    {
     fgui >> id;
     fgui.ignore();
     fgui >> x;
     fgui.ignore();
     fgui >> y;
     fgui.ignore();
     fgui >> im;
     fgui.ignore();
     fgui >> nmsg;
     fgui.ignore();
     fgui.getline(btexto,100);
     
     gui[i][j] = new c_gui_boton(id,x,y,im,btexto);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> Cargado 'boton': ID: " << id << " X: " << x << " Y: " << y << " IMG: " << im << " TEXT: " << btexto << " MENS: " << nmsg << endl;
     gui[i][j]->nmensajes(nmsg);
     // Cargo las instrucciones que pueda llevar el botón.
     for(unsigned int r = 0;r < nmsg;r++)
     {
      char mtipo[30];
      fgui.getline(mtipo,100,':');
      // De cambio de menú.
      if(comparar("G_CGUI",mtipo))
      {
       int g_cgui;
       fgui >> g_cgui;
       fgui.ignore();
       msg.mensaje = G_CGUI;
       msg.parametros[0] = g_cgui;
       gui[i][j]->mensaje(r,msg);
      } // De conectar al servidor.
      else if(comparar("G_CONECTAR",mtipo))
      {
       int g_cgui;
       fgui >> g_cgui;
       fgui.ignore();
       msg.mensaje = G_CONECTAR;
       msg.parametros[0] = g_cgui;
       gui[i][j]->mensaje(r,msg);
      } // De servir.
      else if(comparar("G_SERVIR",mtipo))
      {
       fgui.ignore();
       msg.mensaje = G_SERVIR;
       gui[i][j]->mensaje(r,msg);
      } // De cambiar el cursor.
      else if(comparar("G_CCUR",mtipo))
      {
       int g_cur;
       fgui >> g_cur;
       fgui.ignore();
       msg.mensaje = G_CCUR;
       msg.parametros[0] = g_cur;
       gui[i][j]->mensaje(r,msg);
      } // De cambiar el ejército.
      else if(comparar("G_CEJERCITO",mtipo))
      {
       int ejercito;
       fgui >> ejercito;
       fgui.ignore();
       msg.mensaje = G_CEJERCITO;
       msg.parametros[0] = ejercito;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_NMAPA",mtipo))
      {
       fgui.ignore();
       msg.mensaje = G_NMAPA;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_NANCHO",mtipo))
      {
       int ancho;
       fgui >> ancho;
       fgui.ignore();
       msg.mensaje = G_NANCHO;
       msg.parametros[0] = ancho;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_NALTO",mtipo))
      {
       int alto;
       fgui >> alto;
       fgui.ignore();
       msg.mensaje = G_NALTO;
       msg.parametros[0] = alto;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_NNOMBRE",mtipo))
      {
       int idnom;
       fgui >> idnom;
       fgui.ignore();
       msg.mensaje = G_NNOMBRE;
       msg.parametros[0] = idnom;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_REGEN",mtipo))
      {
       fgui.ignore();
       msg.mensaje = G_REGEN;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_TAB_MAPA",mtipo))
      {
       fgui.ignore();
       msg.mensaje = G_TAB_MAPA;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_CMODOB",mtipo))
      {
       fgui.ignore();
       msg.mensaje = G_CMODOB;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_CMODOE",mtipo))
      {
       fgui.ignore();
       msg.mensaje = G_CMODOE;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_EMAPA",mtipo))
      {
       int idlista;
       fgui >> idlista;
       fgui.ignore();
       msg.mensaje = G_EMAPA;
       msg.parametros[0] = idlista;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_EMAPA_A",mtipo))
      {
       fgui.ignore();
       msg.mensaje = G_EMAPA_A;
       gui[i][j]->mensaje(r,msg);
      }
      else if(comparar("G_EMAPA_S",mtipo))
      {
       int idlista;
       fgui >> idlista;
       fgui.ignore();
       msg.mensaje = G_EMAPA_S;
       msg.parametros[0] = idlista;
       gui[i][j]->mensaje(r,msg);
      }
     }
    }
    else if(comparar("imagen",tipo)) // Imágenes.
    {
     fgui >> id;
     fgui.ignore();
     fgui >> x;
     fgui.ignore();
     fgui >> y;
     fgui.ignore();
     fgui >> im;
     fgui.ignore();
     gui[i][j] = new c_gui_imagen(id,x,y,im);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> Cargado 'imagen': ID: " << id << " X: " << x << " Y: " << y << " IMG: " << im << endl;
    }
    else if(comparar("texto",tipo)) // Cuadros de texto.
    {
     fgui >> id;
     fgui.ignore();
     fgui >> x;
     fgui.ignore();
     fgui >> y;
     fgui.ignore();
     fgui >> im;
     fgui.ignore();
     fgui.getline(btexto,100);
     gui[i][j] = new c_gui_texto(id,x,y,im,btexto);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> Cargado 'texto': ID: " << id << " X: " << x << " Y: " << y << " IMG: " << im << " TEXT: " << btexto << endl;
    }
    else if(comparar("ctec",tipo)) // Comprador de tecnologías.
    {
     fgui >> id;
     fgui.ignore();
     fgui >> x;
     fgui.ignore();
     fgui >> y;
     fgui.ignore();
     fgui >> nmsg;
     fgui.ignore();
     gui[i][j] = new c_gui_ctec(id,x,y,nmsg);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> Cargado 'ctec': ID: " << id << " X: " << x << " Y: " << y << " EJERCITO: " << nmsg << endl;
    }
    else if(comparar("cuni",tipo)) // Comprador de unidades.
    {
     fgui >> id;
     fgui.ignore();
     fgui >> x;
     fgui.ignore();
     fgui >> y;
     fgui.ignore();
     fgui >> nmsg;
     fgui.ignore();
     gui[i][j] = new c_gui_cuni(id,x,y,nmsg);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> Cargado 'cuni': ID: " << id << " X: " << x << " Y: " << y << " EJERCITO: " << nmsg << endl;
    }
    else if(comparar("lmapas",tipo))
    {
     fgui >> id;
     fgui.ignore();
     fgui >> x;
     fgui.ignore();
     fgui >> y;
     fgui.ignore();
     gui[i][j] = new c_gui_lmapas(id,x,y);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> Cargado 'lmapas': ID: " << id << " X: " << x << " Y: " << y << endl;
    }
   }
   if(_M_G_DEBUG_)
    cout << "[svideo]-> Cargada gui '" << nfgui << "'" << endl;
   fgui.close();
  }
  // Cargo las fuentes.
  fconfig >> nfuentes;
  fuente = new TTF_Font*[nfuentes];
  fconfig.ignore();
  for(unsigned int i = 0;i < nfuentes;i++)
  {
   char dirfuente[255];
   fconfig.getline(dirfuente,255);
   fuente[i] = TTF_OpenFont(dirfuente,30);
  }
 }
 fconfig.close();
 
 // Cargo las imágenes de los menús.
 fstream fimagenes("./config/imagenes.list",ios_base::in);
 {
  fimagenes >> nimagenes;
  fimagenes.ignore();
  imagen = new SDL_Surface*[nimagenes];
  for(unsigned int i = 0;i < nimagenes;i++)
  {
   char nombre[100];
   fimagenes.getline(nombre,100);
   imagen[i] = NULL;
   imagen[i] = IMG_Load(nombre);
   imagen[i] = SDL_ConvertSurface(imagen[i],imagen[i]->format,SDL_HWSURFACE);
   if(_M_G_DEBUG_)
    if(imagen[i] != NULL)
     cout << "[svideo]-> Cargada imagen: " << nombre << endl;
    else
     cout << "[svideo]-> Fallo al cargar imagen: " << nombre << endl;
  }
 }
 fimagenes.close();
 if(_M_G_DEBUG_)
  cout << "[svideo]-> Fin carga imagenes." << endl;
 
 // Cargo las imagenes de las unidades patriotas (LOGOS).
 fstream fup("./config/up-logo.img",ios_base::in);
 {
  unsigned int nup;
  fup >> nup;
  fup.ignore();
  UP = new SDL_Surface*[nup];
  if(_M_G_DEBUG_)
   cout << "[svideo]-> Numero de logos patriotas: " << nup << endl;
  for(unsigned int i = 0;i < nup;i++)
  {
   char dir[101];
   fup.getline(dir,100);
   UP[i] = NULL;
   UP[i] = IMG_Load(dir);
   if(_M_G_DEBUG_)
    if(UP[i] == NULL)
     cout << "[svideo]-> CARGA DE LOGO UNIDAD FALLIDA: PATRIOTA: " << i << endl;
    else
     cout << "[svideo]-> CARGA DE LOGO UNIDAD: PATRIOTA: " << i << endl;
  }
 }
 fup.close();
 
 // Cargo las imagenes de las unidades invasoras (LOGOS).
 fstream fui("./config/ui-logo.img",ios_base::in);
 {
  unsigned int nui;
  fui >> nui;
  fui.ignore();
  UI = new SDL_Surface*[nui];
  if(_M_G_DEBUG_)
   cout << "[svideo]-> Numero de logos invasores: " << nui << endl;
  for(unsigned int i = 0;i < nui;i++)
  {
   char dir[101];
   fui.getline(dir,100);
   UI[i] = NULL;
   UI[i] = IMG_Load(dir);
   if(_M_G_DEBUG_)
    if(UI[i] == NULL)
     cout << "[svideo]-> CARGA DE LOGO UNIDAD FALLIDA: INVASORA: " << i << endl;
    else
     cout << "[svideo]-> CARGA DE LOGO UNIDAD: INVASORA: " << i << endl;
  }
 }
 fui.close();

 // Cargo el tile de movimiento.
 //tiles = IMG_Load("./graficos/tilesel.png");

 // Inicializo variables de batalla.
 posmapax = 0;
 posmapay = 0;
 
 FLAGS = 0;
 // Pongo modo ventana, sin escritura.
 FLAGS = FLAGS & ~OF_P_COMPLETA;
 FLAGS = FLAGS & ~OF_ESCRITURA;

 // Inicializo el gestor de conversaciones.
 ndialogo = new char[100];
 ndialogo[0] = '\000';
 Sndialogo = NULL;

 // Inicializo variables de menú.
 gtec = NULL;
 guni = NULL;

 // Cargo los cursores.
 cursor[0] = IMG_Load("./graficos/cursor1.png");
 cursor[1] = IMG_Load("./graficos/cursor2.png");

 // Elijo el cursor aleatoriamente.
 srand(time(NULL));
 ncursor = rand()%2;
 
 // Pongo el modo menú y preparo la carga del primer menú.
 FLAGS = FLAGS | OF_MODO_MENU;
 uigui = 0;
 texto = NULL;
 
 texto = new SDL_Surface*[nogui[0]];

 for(unsigned int recorredor = 0;recorredor < nogui[0];recorredor++)
  texto[recorredor] = NULL;

 SDL_Color colorfuente;
 colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;

 for(unsigned int i = 0;i < nogui[0];i++)
  if(gui[0][i]->tipo() == G_T_BOTON)
   texto[i] = TTF_RenderText_Blended(fuente[0],gui[0][i]->texto(),colorfuente);
 
 tablero.asociar_svideo(this);
 // Quito el minimapa.
 FLAGS = FLAGS & ~OF_MINIMAPA;
 pantallamenu = SDL_CreateRGBSurface(SDL_HWSURFACE,640,480,32,0,0,0,0);
 pregenerar_menu();
 contador_n_mensaje = 80;
 vvida = NULL;
}

/*******************************************************************************
/
/ método fin_batalla
/
/ Termina la batalla.
/ Prepara muestra de pantalla de final de partida y cambia los option flags.
/
*******************************************************************************/

void c_svideo::fin_batalla(int f)
{
 if(f)
 resultado = 30;
 else
 resultado = 31;
 FLAGS = FLAGS | OF_FIN_BATALLA;
}

/*******************************************************************************
/
/ método mapaelegido.
/
/ Asocia el mapa elegido al tablero.
/
*******************************************************************************/

void c_svideo::mapaelegido(c_mapa mapae)
{
 tablero.asociar_mapa(mapae);
}

/*******************************************************************************
/
/ método jugador_local
/
/ asocia los datos del jugador local al tablero.
/
*******************************************************************************/

void c_svideo::jugador_local(int ejer,vector<personaje> p,vector<coordenada> c)
{
 if(_M_G_DEBUG_)
  cout << "[svideo]-> jugador_local inicio..."<< ejer << endl;
 tablero.jugador_local(ejer,p,c);
 if(_M_G_DEBUG_)
  cout << "[svideo]-> jugador_local final." << endl;
}

/*******************************************************************************
/
/ método jugador_remoto
/
/ asocia los datos del jugador remoto al tablero.
/
*******************************************************************************/

void c_svideo::jugador_remoto(int ejer,vector<personaje> p,vector<coordenada> c)
{
 if(_M_G_DEBUG_)
  cout << "[svideo]-> jugador_remoto inicio..." << ejer << endl;
 tablero.jugador_remoto(ejer,p,c);
 if(_M_G_DEBUG_)
  cout << "[svideo]-> jugador_remoto final." << endl;
}

/*******************************************************************************
/
/ método cambiargui
/
/ cambia de un menú a otro
/
*******************************************************************************/

void c_svideo::cambiargui(unsigned int i)
{
 if(_M_G_DEBUG_)
  cout << "[svideo]-> Cambiando a gui: " << i << endl;
 // Se libera el espacio de las texturas.
 for(unsigned int ctex = 0;ctex < nogui[uigui];ctex++)
  if(gui[uigui][ctex]->tipo() == G_T_BOTON || gui[uigui][ctex]->tipo() == G_T_TEXTO)
   SDL_FreeSurface(texto[ctex]);

 // Se libera el espacio de las descripciones.
 delete texto;
  if(_M_G_DEBUG_)
  cout << "[svideo]-> Liberando espacio de las descripciones." << endl;
 for(unsigned int ctex = 0;ctex < nogui[uigui];ctex++)
 {
  if(gui[uigui][ctex]->tipo() == G_T_CTEC)
  {
   for(unsigned int cdesc = 0;cdesc < compra.size();cdesc++)
   {
    if(gtec[cdesc] != NULL)
    {
     delete gtec[cdesc];
     gtec[cdesc] = NULL;
    }
   }
   delete gtec;
   gtec = NULL;
  }
  if(gui[uigui][ctex]->tipo() == G_T_CUNI)
  {
   for(unsigned int cdesc = 0;cdesc < compra.size();cdesc++)
   {
    if(guni[cdesc] != NULL)
    {
     delete guni[cdesc];
     guni[cdesc] = NULL;
    }
   }
   delete guni;
   guni = NULL;
  }
 }
 if(_M_G_DEBUG_)
  cout << "[svideo]-> Liberado espacio de las descripciones." << endl;

 // Se deshabilita la escritura.
 if(_M_G_DEBUG_)
  cout << "[svideo]-> Liberado espacio de texturas de texto." << endl;
 sentrada->descritura();
 
 // Se efectua el cambio.
 uigui = i;

 // Se reserva memoria.
 texto = new SDL_Surface*[nogui[i]];
 
 for(unsigned int recorredor = 0;recorredor < nogui[i];recorredor++)
  texto[recorredor] = NULL;


 if(_M_G_DEBUG_)
  cout << "[svideo]-> Reservado espacio de texturas de texto." << endl;

 SDL_Color colorfuente;
 colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;

 // Se renderiza texto y se hacen consultas al núcleo sobre compras en caso de que
 // se necesite.
 for(unsigned int r = 0;r < nogui[i];r++)
 {
  if(_M_G_DEBUG_)
  cout << "[svideo]-> Generando textura para objeto: " << r << endl;
  if(gui[i][r]->tipo() == G_T_BOTON || gui[i][r]->tipo() == G_T_TEXTO)
   texto[r] = TTF_RenderText_Blended(fuente[0],gui[i][r]->texto(),colorfuente);
  if(gui[i][r]->tipo() == G_T_CTEC)
  {
  if(_M_G_DEBUG_)
   cout << "[svideo]-> Revisando compras tecnológicas." << endl;
   revisarcomprastec(gui[i][r]->nmensajes());
  if(_M_G_DEBUG_)
   cout << "[svideo]-> Revisadas compras tecnológicas." << endl;
  }
  if(gui[i][r]->tipo() == G_T_CUNI)
  {
   revisarcomprasuni(gui[i][r]->nmensajes());
  }
  if(gui[i][r]->tipo() == G_T_LMAPAS)
  {
   if(_M_G_DEBUG_)
    cout << "[svideo]-> Revisando lista de mapas." << endl;
   c_mapa * lista = nucleo->listar_mapas();
   MD5.clear();
   texto_mapas.clear();
   cout << "NUMEROMAPAS: " << nucleo->num_maps() << endl;
   for(int s = 0;s < nucleo->num_maps();s++)
   {
    char * temp;
    temp = new char[33];
    strcpy(temp,lista[s].md5());
    MD5.push_back(temp);
    temp = new char[101];
    strcpy(temp,lista[s].nombrefichero());
    if(comparar(temp,""))
     strcpy(temp,"Sin nombre.");
    texto_mapas.push_back(TTF_RenderText_Blended(fuente[0],temp,colorfuente));
   }
   gui[i][r]->atexto((char)0);
   gui[i][r]->atexto((char)0);
  }
 }
 if(_M_G_DEBUG_)
  cout << "[svideo]-> Gui cambiada." << endl;
 pregenerar_menu();
}

/*******************************************************************************
/
/ Método pantallacompleta
/
/ Cambia de modo ventana a modo pantalla completa y viceversa.
/
*******************************************************************************/

void c_svideo::pantallacompleta()
{
 if(FLAGS & OF_P_COMPLETA)
 {
  pantalla = SDL_SetVideoMode(640,480,24,SDL_HWSURFACE|SDL_DOUBLEBUF);
  FLAGS = FLAGS & ~OF_P_COMPLETA;
 }
 else
 {
  pantalla = SDL_SetVideoMode(640,480,24,SDL_HWSURFACE|SDL_DOUBLEBUF|SDL_FULLSCREEN);
  FLAGS =  FLAGS | OF_P_COMPLETA;
 }
}

/*******************************************************************************
/
/ método revisarcomprastec
/
/ reorganiza la lista de compras de tecnologías y sus texturas consultando
/ al núcleo.
/
*******************************************************************************/

void c_svideo::revisarcomprastec(int ejercito)
{
 // Libero espacio ocupado por las anteriores compras.
 for(unsigned int gt = 0;gtec != NULL && gt < compra.size();gt++)
 {
  if(gtec[gt] != NULL)
  delete gtec[gt];
 }
 if(_M_G_DEBUG_)
  cout << "[svideo]-> Liberado espacio de las descripciones." << endl;
 if(gtec != NULL)
  delete gtec;
 while(compra.size())
 {
  compra.pop_back();
 }
 // Reservo espacio para las nuevas compras.
 compra = nucleo->nuevas_tecs(ejercito);
 if(_M_G_DEBUG_)
  cout << "[svideo]-> LONGITUD DEL VECTOR DE COMPRAS DESPUES DE REVISAR: " << compra.size() << endl;
 compraactual = 0;
 gtec = new c_gtec*[compra.size()];
 vector<tecnologias> vt = nucleo->tecs(ejercito);
 for(unsigned int gt = 0;gt < compra.size();gt++)
 {
  if(_M_G_DEBUG_)
  {
   cout << "[svideo]-> LE PASO A nivel_tec: " << ejercito << " tec: " << compra[gt] << endl;
  }
  // Las creo.
  gtec[gt] = new c_gtec(vt[compra[gt]].nombre,vt[compra[gt]].coste,nucleo->nivel_tec(ejercito,compra[gt]),vt[compra[gt]].num_desc,vt[compra[gt]].desc,fuente[0]);
 }
 char * din;
 din = intachar(nucleo->dinero());
 char fondos[100];
 strcpy(fondos,"Fondos: ");
 strcat(fondos,din);
 delete din;
 // Dibujo el dinero.
 SDL_Color colorfuente;
 colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;
 dinero = TTF_RenderText_Blended(fuente[0],fondos,colorfuente);
}

/*******************************************************************************
/
/ método revisarcomprasuni
/
/ reorganiza la lista de compras de unidades y sus texturas consultando
/ al núcleo.
/
*******************************************************************************/

void c_svideo::revisarcomprasuni(int ejercito)
{
 // Se libera espacio ocupado por las antiguas compras.
 for(unsigned int gt = 0;guni != NULL && gt < compra.size();gt++)
 {
  if(guni[gt] != NULL)
  delete guni[gt];
 }
 if(guni != NULL)
 {
  delete guni;
  guni = NULL;
 }
 while(compra.size())
 {
  compra.pop_back();
 }
 if(_M_G_DEBUG_)
  cout << "[svideo]-> Se van a revisar unidades del ejército: " << ejercito << endl;
 // Se consultan y se reserva espacio para las nuevas compras.
 compra = nucleo->nuevas_uds(ejercito);
 if(_M_G_DEBUG_)
  cout << "[svideo]-> LONGITUD DEL VECTOR DE COMPRAS DESPUES DE REVISAR: " << compra.size() << endl;
 compraactual = 0;
 /////////
 guni = new c_guni*[compra.size()];
 vector<personaje> vp = nucleo->unidades(ejercito);
 for(unsigned int gu = 0;gu < compra.size();gu++)
 {
  if(_M_G_DEBUG_)
  {
   cout << "[svideo]-> Unidad: nombre: " << vp[compra[gu]].nombre << endl;
  }
  // Se crean.
  guni[gu] = new c_guni(vp[compra[gu]].nombre,vp[compra[gu]].coste,vp[compra[gu]].alcance_ataque,vp[compra[gu]].danio_ataque,vp[compra[gu]].blindaje,vp[compra[gu]].mov,vp[compra[gu]].vida,nucleo->num_unidades(ejercito,vp[compra[gu]].id),vp[compra[gu]].num_desc,vp[compra[gu]].desc,fuente[0]);
 }
 char * din;
 din = intachar(nucleo->dinero());
 char fondos[100];
 strcpy(fondos,"Fondos: ");
 strcat(fondos,din);
 delete din;
 // Dibujo el dinero.
 SDL_Color colorfuente;
 colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;
 dinero = TTF_RenderText_Blended(fuente[0],fondos,colorfuente);
}

/*******************************************************************************
/
/ método colision
/
/ Comprueba las colisiones del ratón con el menú o las unidades en el modo batalla.
/
*******************************************************************************/

void c_svideo::colision(unsigned int x,unsigned int y)
{
 // Si estamos en el modo menú, compruebo que no halla colisionado con cada objeto
 // interactivo. En caso de que halla colisionado, lanzo las órdenes que lleve asignadas
 if(FLAGS & OF_MODO_MENU)
 {
  for(unsigned int i = 0;i < nogui[uigui];i++)
  {
   if(gui[uigui][i]->tipo() == G_T_BOTON)
   { // Si colisiona con un botón, se lanzan sus órdenes.
    if((gui[uigui][i]->x() < x) && ((x - gui[uigui][i]->x()) < (unsigned int)imagen[gui[uigui][i]->imagen()]->w) && (gui[uigui][i]->y() < y) && ((y - gui[uigui][i]->y()) < (unsigned int)imagen[gui[uigui][i]->imagen()]->h))
    {
     ssonido->click();
     lanzar(gui[uigui][i]);
    }
   }
   else if(gui[uigui][i]->tipo() == G_T_TEXTO)
   { // Si se colisiona con un cuadro de texto, se habilita escritura y se enfoca.
    if((gui[uigui][i]->x() < x) && ((x - gui[uigui][i]->x()) < (unsigned int)imagen[gui[uigui][i]->imagen()]->w) && (gui[uigui][i]->y() < y) && ((y - gui[uigui][i]->y()) < (unsigned int)imagen[gui[uigui][i]->imagen()]->h))
    {
     objetivoescritura = i;
     sentrada->hescritura();
    }
   }
   else if(gui[uigui][i]->tipo() == G_T_CTEC)
   { // Si se colisiona con un cuadro de tecnologias, se comprueba que se pase de tecnología
     // o se compre.
    if(((gui[uigui][i]->x() + 10) < x) && ((gui[uigui][i]->x() + 50) > x) && ((gui[uigui][i]->y() + 50) < y) && ((gui[uigui][i]->y() + 250) > y) && (compra.size() > 0))
     if(compraactual)
     {
      compraactual--;
      pregenerar_menu();
     }
    if(((gui[uigui][i]->x() + 550) < x) && ((gui[uigui][i]->x() + 590) > x) && ((gui[uigui][i]->y() + 50) < y) && ((gui[uigui][i]->y() + 250) > y) && (compra.size() > 0))
    {
     if(compraactual != (compra.size()-1))
     {
      compraactual = (compraactual + 1) % compra.size();
      pregenerar_menu();
     }
    }
    if(((gui[uigui][i]->x() + 510) < x) && ((gui[uigui][i]->x() + 590) > x) && ((gui[uigui][i]->y() + 9 ) < y) && ((gui[uigui][i]->y() + 49 ) > y))
    {
     if(_M_G_DEBUG_)
      cout << "[svideo]-> INTENTANDO COMPRAR TEC: " << nucleo->tecs(gui[uigui][i]->nmensajes())[compra[compraactual]].num_tecnologia << " QUE ES COMPRA: " << compraactual << endl;
     nucleo->comprar_tecnologia(gui[uigui][i]->nmensajes(),nucleo->tecs(gui[uigui][i]->nmensajes())[compra[compraactual]].num_tecnologia);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> COMPRADO REVISANDO COMPRAS" << endl;
     revisarcomprastec(gui[uigui][i]->nmensajes());
     if(_M_G_DEBUG_)
      cout << "[svideo]-> COMPRAS REVISADAS" << endl;
     pregenerar_menu();
    }
   }
   else if(gui[uigui][i]->tipo() == G_T_CUNI)
   { // Si se colisiona con un cuadro de unidades, se comprueba que se pase de unidad o se compre.
    if(((gui[uigui][i]->x() + 10) < x) && ((gui[uigui][i]->x() + 50) > x) && ((gui[uigui][i]->y() + 50) < y) && ((gui[uigui][i]->y() + 250) > y) && (compra.size() > 0))
     if(compraactual)
     {
      compraactual--;
      pregenerar_menu();
     }
    if(((gui[uigui][i]->x() + 550) < x) && ((gui[uigui][i]->x() + 590) > x) && ((gui[uigui][i]->y() + 50) < y) && ((gui[uigui][i]->y() + 250) > y) && (compra.size() > 0))
    {
     if(compraactual != (compra.size()-1))
     {
      compraactual = (compraactual + 1) % compra.size();
      pregenerar_menu();
     }
    }
    if(((gui[uigui][i]->x() + 510) < x) && ((gui[uigui][i]->x() + 590) > x) && ((gui[uigui][i]->y() + 9 ) < y) && ((gui[uigui][i]->y() + 49 ) > y))
    {
     if(_M_G_DEBUG_)
      cout << "[svideo]-> INTENTANDO COMPRAR UNI: " << nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id << " QUE ES COMPRA: " << compraactual << endl;     
     nucleo->comprar_unidad(gui[uigui][i]->nmensajes(),nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id);
     if(_M_G_DEBUG_)
      cout << "[svideo]-> COMPRADO REVISANDO COMPRAS" << endl;
     revisarcomprasuni(gui[uigui][i]->nmensajes());
     if(_M_G_DEBUG_)
      cout << "[svideo]-> COMPRAS REVISADAS" << endl;
     pregenerar_menu();
    }
   }
   else if(gui[uigui][i]->tipo() == G_T_LMAPAS)
   { // Si se colisiona con un cuadro de unidades, se comprueba que se pase de mapa o se elija uno.
    if((gui[uigui][i]->x() < x) && ((x - gui[uigui][i]->x()) < (unsigned int)imagen[gui[uigui][i]->imagen()]->w) && (gui[uigui][i]->y() < y) && ((y - gui[uigui][i]->y()) < (unsigned int)imagen[gui[uigui][i]->imagen()]->h))
    {
     if(x > gui[uigui][i]->x() + 565 && x < gui[uigui][i]->x() + 595)
     {
      if(y > gui[uigui][i]->y() + 5 && y < gui[uigui][i]->y() + 35)
      {
       if(gui[uigui][i]->g_texto[1] > 0)
       {
        gui[uigui][i]->g_texto[1]--;
        pregenerar_menu();
       }
      }
      if(y > gui[uigui][i]->y() + 265 && y < gui[uigui][i]->y() + 295)
      {
       if(nucleo->num_maps() - gui[uigui][i]->g_texto[1] > 7)
       {
        gui[uigui][i]->g_texto[1]++;
        pregenerar_menu();
       }
      }
     }
     else if(x > gui[uigui][i]->x() + 8 && x < gui[uigui][i]->x() + 565)
     {
      int sector = 0;
      int presector = gui[uigui][i]->g_texto[0];
      while(y > gui[uigui][i]->y())
      {
       if(y > gui[uigui][i]->y() + 8 && y < gui[uigui][i]->y() + 45)
       {
        if(sector + 1 <= nucleo->num_maps())
        {
         gui[uigui][i]->g_texto[0] = gui[uigui][i]->g_texto[1] + sector;
         if(presector != sector)
         pregenerar_menu();
        }
        y = 40;
       }
       y -= 40;
       sector++;
      }
     }
    }
   }
  }
 }
 else
 { // Se comprueba la pulsación a cualquiera de los botones.
  if(FLAGS & OF_MODO_EDICION)
  {
   if(y < 440)
   {
    FLAGS = FLAGS | OF_DIBUJANDO;
   }
   else
   {
    if(y > 445 && y < 475)
    {
     if(x > 180 && x < 262)
      tablero.epincel(0);
     else if(x > 272 && x < 354)
      tablero.epincel(1);
     else if(x > 364 && x < 446)
      tablero.epincel(2);
     else if(x > 456 && x < 538)
      tablero.epincel(3);
     else if(x > 538 && x < 578)
     {
      if(FLAGS & OF_MAPA_EDITADO)
      {
       nucleo->borra_mapa(tablero.mapa_actual().md5());
       FLAGS = FLAGS & ~OF_MAPA_EDITADO;
      }
      nucleo->guardar_mapa(tablero.mapa_actual());
      c_sv_mensaje msg;
      msg.mensaje = G_CGUI;
      msg.parametros[0] = 0;
      mensajes.push(msg);
      msg.mensaje = G_QMODOE;
      mensajes.push(msg);
      msg.mensaje = G_QMODOB;
      mensajes.push(msg);
     }
     else if(x > 580 && x < 620)
     {
      c_sv_mensaje msg;
      msg.mensaje = G_CGUI;
      msg.parametros[0] = 0;
      mensajes.push(msg);
      msg.mensaje = G_QMODOE;
      mensajes.push(msg);
      msg.mensaje = G_QMODOB;
      mensajes.push(msg);
     }
    }
   }
  }
  else
  {
   if(FLAGS & OF_VIDA)
    FLAGS = FLAGS & ~OF_VIDA;
   if(FLAGS & OF_FIN_BATALLA)
   {
    FLAGS = FLAGS & ~OF_FIN_BATALLA;
    FLAGS = FLAGS | OF_MODO_MENU;
    cambiargui(0);
   }
   else
   {
    // En el modo batalla si estoy por encima de la barra, compruebo, si es mi turno, que halla
    // hecho click en alguna unidad, para moverla. Si ya he hecho click en alguna unidad compruebo
    // que me quiera mover, atacar o no hacer nada.
    if(y < 440)
    {
     if(!(FLAGS & OF_ESCRITURA))
     {
      if(nucleo->devuelve_turno())
      {
       tablero.click(x,y);
      }
     }
     else
     {
      if(x > 580 && x < 630 && y > 372 && y < 402)
      {
       if(strlen(ndialogo))
       {
        sred->nuevomensaje(mens(ndialogo));
        dialogo.push_back(Sndialogo);
        if(dialogo.size() > 10)
         dialogo.pop_front();
        ndialogo[0] = '\000';
        Sndialogo = NULL;
       }
      }
     }
    }
    else
    {
     // Si estoy en la barra compruebo que le halla dado a alguno de los botones.
     if(x > 580 && x < 630 && y > 445 && y < 475)
     {
      if(FLAGS & OF_ESCRITURA)
      {
       FLAGS = FLAGS & ~OF_ESCRITURA;
       sentrada->descritura();
      }
      else
      {
       FLAGS = FLAGS | OF_ESCRITURA;
       FLAGS = FLAGS & ~OF_NUEVO_MENS;
       sentrada->hescritura();
      }
     }
     if(x > 510 && x < 560 && y > 445 && y < 475)
     {
      if(nucleo->devuelve_turno())
       nucleo->termina_turno();
     }
    }
   }
  }
  if(x > 120 && x < 170 && y > 450 && y < 470)
  {
   if(FLAGS & OF_MINIMAPA)
    FLAGS = FLAGS & ~OF_MINIMAPA;
   else
    FLAGS = FLAGS | OF_MINIMAPA;
  }
 }
}

/*******************************************************************************
/
/ método decolision
/
/ Se desactiva la opción dibujando.
/
*******************************************************************************/

void c_svideo::decolision()
{
 FLAGS = FLAGS & ~OF_DIBUJANDO;
}

/*******************************************************************************
/
/ método lanzar
/
/ Lanza las ordenes que tenga un objeto del menú.
/
*******************************************************************************/

void c_svideo::lanzar(c_objeto_gui * cog)
{
 for(unsigned int i = 0;i < cog->nmensajes();i++)
  mensajes.push(cog->mensaje(i));
}

/*******************************************************************************
/
/ método acaracter
/
/ Añade un carácter al objeto en pantalla que pueda recibirlo.
/
*******************************************************************************/

void c_svideo::acaracter(char m)
{
 // Si está activado el modo escritura, será el cuadro de diálogos (chat).
 if(FLAGS & OF_ESCRITURA)
 {
  ndialogo[strlen(ndialogo)+1] = '\000';
  ndialogo[strlen(ndialogo)] = m;
  SDL_Color colorfuente;
  colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;
  if(Sndialogo != NULL)
   SDL_FreeSurface(Sndialogo);
  Sndialogo = TTF_RenderText_Blended(fuente[0],ndialogo,colorfuente);
 }
 else // Si no, será un objeto de menú de tipo texto.
 {
  gui[uigui][objetivoescritura]->atexto(m);
  SDL_Color colorfuente;
  colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;
  SDL_FreeSurface(texto[objetivoescritura]);
  texto[objetivoescritura] = TTF_RenderText_Blended(fuente[0],gui[uigui][objetivoescritura]->texto(),colorfuente);
  pregenerar_menu();
 }
}

/*******************************************************************************
/
/ método bcaracter
/
/ Borra un carácter al objeto en pantalla que deba borrarlo.
/
*******************************************************************************/

void c_svideo::bcaracter()
{
 // Si está activo el modo escritura, lo borro de la ventana de diálogo (chat)
 if(FLAGS & OF_ESCRITURA)
 {
  if(ndialogo[0] != '\000')
  {
   ndialogo[strlen(ndialogo)-1] = '\000';
   SDL_Color colorfuente;
   colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;
   if(Sndialogo != NULL)
    SDL_FreeSurface(Sndialogo);
   if(strlen(ndialogo) > 0)
    Sndialogo = TTF_RenderText_Blended(fuente[0],ndialogo,colorfuente);
   else
    Sndialogo = NULL;
  }
 }
 else // Si no lo borro de un objeto de menú (tipo texto).
 {
  gui[uigui][objetivoescritura]->rtexto();
  SDL_Color colorfuente;
  colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 0;
  SDL_FreeSurface(texto[objetivoescritura]);
  texto[objetivoescritura] = TTF_RenderText_Blended(fuente[0],gui[uigui][objetivoescritura]->texto(),colorfuente);
  pregenerar_menu();
 }
}

/*******************************************************************************
/
/ método mensajeremoto
/
/ Añade un mensaje al cuadro de diálogo.
/
*******************************************************************************/

void c_svideo::mensajeremoto(char * mens)
{
 // Lo renderizo y lo añado. Si Ya hay 10 mensajes, borro el primero.
 if(!(FLAGS & OF_ESCRITURA))
  FLAGS = FLAGS | OF_NUEVO_MENS;
 SDL_Surface * mensremoto;
 SDL_Color colorfuente;
 colorfuente.r = 0; colorfuente.g = 0; colorfuente.b = 255;
 mensremoto = TTF_RenderText_Blended(fuente[0],mens,colorfuente);
 dialogo.push_back(mensremoto);
 if(dialogo.size() > 10)
  dialogo.pop_front();
}

/*******************************************************************************
/
/ método pregenerar_menu
/
/ Predibuja los menús en un buffer temporal. Para no estar recalculando y 
/ redibujando inutilmente durante cada frame.
/
*******************************************************************************/

void c_svideo::pregenerar_menu()
{
 for(unsigned int i = 0;i < nogui[uigui];i++)
  {
   switch(gui[uigui][i]->tipo())
   {
    case G_T_BOTON:
    {
     SDL_Rect destino;
     destino.x = gui[uigui][i]->x();
     destino.y = gui[uigui][i]->y();
     destino.w = imagen[gui[uigui][i]->imagen()]->w;
     destino.h = imagen[gui[uigui][i]->imagen()]->h;
     SDL_BlitSurface(imagen[gui[uigui][i]->imagen()],NULL,pantallamenu,&destino);
     destino.x = destino.x + (destino.w / 2) - (texto[i]->w / 2);
     destino.y = destino.y + (destino.h / 2) - (texto[i]->h / 2);
     destino.w = texto[i]->w;
     destino.h = texto[i]->h;
     SDL_BlitSurface(texto[i],NULL,pantallamenu,&destino);
    } break;
    case G_T_IMAGEN:
    {
     SDL_Rect destino;
     destino.x = gui[uigui][i]->x();
     destino.y = gui[uigui][i]->y();
     destino.w = imagen[gui[uigui][i]->imagen()]->w;
     destino.h = imagen[gui[uigui][i]->imagen()]->h;
     SDL_BlitSurface(imagen[gui[uigui][i]->imagen()],NULL,pantallamenu,&destino);
    } break;
    case G_T_TEXTO:
    {
     SDL_Rect destino;
     destino.x = gui[uigui][i]->x();
     destino.y = gui[uigui][i]->y();
     destino.w = imagen[gui[uigui][i]->imagen()]->w;
     destino.h = imagen[gui[uigui][i]->imagen()]->h;
     SDL_BlitSurface(imagen[gui[uigui][i]->imagen()],NULL,pantallamenu,&destino);
     destino.x = destino.x + (destino.w / 2) - (texto[i]->w / 2);
     destino.y = destino.y + (destino.h / 2) - (texto[i]->h / 2);
     destino.w = texto[i]->w;
     destino.h = texto[i]->h;
     SDL_BlitSurface(texto[i],NULL,pantallamenu,&destino);
    } break;
    case G_T_CTEC:
    {
     SDL_Rect destino;
     destino.x = gui[uigui][i]->x();
     destino.y = gui[uigui][i]->y();
     destino.w = imagen[4]->w;
     destino.h = imagen[4]->h;
     SDL_BlitSurface(imagen[4],NULL,pantallamenu,&destino);
     destino.x = gui[uigui][i]->x() + 10;
     destino.y = gui[uigui][i]->y() + 50;
     destino.w = imagen[5]->w;
     destino.h = imagen[5]->h;
     SDL_BlitSurface(imagen[5],NULL,pantallamenu,&destino);
     destino.x = gui[uigui][i]->x() + 550;
     SDL_BlitSurface(imagen[6],NULL,pantallamenu,&destino);
     if(compra.size() > 0)
     {
      destino.x = gui[uigui][i]->x() + 20;
      destino.y = gui[uigui][i]->y() + 10;
      destino.w = gtec[compraactual]->nom->w;
      destino.h = gtec[compraactual]->nom->h;
      SDL_BlitSurface(gtec[compraactual]->nom,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 300;
      destino.y = gui[uigui][i]->y() + 10;
      destino.w = gtec[compraactual]->coste->w;
      destino.h = gtec[compraactual]->coste->h;
      SDL_BlitSurface(gtec[compraactual]->coste,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 55;
      destino.y = gui[uigui][i]->y() + 45;
      destino.w = gtec[compraactual]->nivel->w;
      destino.h = gtec[compraactual]->nivel->h;
      SDL_BlitSurface(gtec[compraactual]->nivel,NULL,pantallamenu,&destino);
      for(unsigned int ndesc = 0;ndesc < gtec[compraactual]->ndesc ;ndesc++)
      {
       destino.x = gui[uigui][i]->x() + 55;
       destino.y = gui[uigui][i]->y() + 70 + 25*ndesc;
       destino.w = gtec[compraactual]->desc[ndesc]->w;
       destino.h = gtec[compraactual]->desc[ndesc]->h;
       SDL_BlitSurface(gtec[compraactual]->desc[ndesc],NULL,pantallamenu,&destino);
      }
      destino.x = gui[uigui][i]->x()+510;
      destino.y = gui[uigui][i]->y()+9;
      destino.w = imagen[7]->w;
      destino.h = imagen[7]->h;
      SDL_BlitSurface(imagen[7],NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x()+10;
      destino.y = gui[uigui][i]->y()+250;
      destino.w = dinero->w;
      destino.h = dinero->h;
      SDL_BlitSurface(dinero,NULL,pantallamenu,&destino);
     }
    } break;
    case G_T_CUNI:
    {
     SDL_Rect destino;
     destino.x = gui[uigui][i]->x();
     destino.y = gui[uigui][i]->y();
     destino.w = imagen[4]->w;
     destino.h = imagen[4]->h;
     SDL_BlitSurface(imagen[4],NULL,pantallamenu,&destino);
     destino.x = gui[uigui][i]->x() + 10;
     destino.y = gui[uigui][i]->y() + 50;
     destino.w = imagen[5]->w;
     destino.h = imagen[5]->h;
     SDL_BlitSurface(imagen[5],NULL,pantallamenu,&destino);
     destino.x = gui[uigui][i]->x() + 550;
     SDL_BlitSurface(imagen[6],NULL,pantallamenu,&destino);
     if(compra.size() > 0)
     {
      destino.x = gui[uigui][i]->x() + 20;
      destino.y = gui[uigui][i]->y() + 10;
      destino.w = guni[compraactual]->nom->w;
      destino.h = guni[compraactual]->nom->h;
      SDL_BlitSurface(guni[compraactual]->nom,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 300;
      destino.y = gui[uigui][i]->y() + 10;
      destino.w = guni[compraactual]->coste->w;
      destino.h = guni[compraactual]->coste->h;
      SDL_BlitSurface(guni[compraactual]->coste,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 55;
      destino.y = gui[uigui][i]->y() + 40;
      destino.w = guni[compraactual]->alc->w;
      destino.h = guni[compraactual]->alc->h;
      SDL_BlitSurface(guni[compraactual]->alc,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 300;
      destino.y = gui[uigui][i]->y() + 40;
      destino.w = guni[compraactual]->dan->w;
      destino.h = guni[compraactual]->dan->h;
      SDL_BlitSurface(guni[compraactual]->dan,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 55;
      destino.y = gui[uigui][i]->y() + 70;
      destino.w = guni[compraactual]->blin->w;
      destino.h = guni[compraactual]->blin->h;
      SDL_BlitSurface(guni[compraactual]->blin,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 300;
      destino.y = gui[uigui][i]->y() + 70;
      destino.w = guni[compraactual]->mov->w;
      destino.h = guni[compraactual]->mov->h;
      SDL_BlitSurface(guni[compraactual]->mov,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 55;
      destino.y = gui[uigui][i]->y() + 100;
      destino.w = guni[compraactual]->vid->w;
      destino.h = guni[compraactual]->vid->h;
      SDL_BlitSurface(guni[compraactual]->vid,NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x() + 300;
      destino.y = gui[uigui][i]->y() + 100;
      destino.w = guni[compraactual]->num->w;
      destino.h = guni[compraactual]->num->h;
      SDL_BlitSurface(guni[compraactual]->num,NULL,pantallamenu,&destino);
      for(unsigned int ndesc = 0;ndesc < guni[compraactual]->ndesc ;ndesc++)
      {
       destino.x = gui[uigui][i]->x() + 55;
       destino.y = gui[uigui][i]->y() + 130 + 25*ndesc;
       destino.w = guni[compraactual]->desc[ndesc]->w;
       destino.h = guni[compraactual]->desc[ndesc]->h;
       SDL_BlitSurface(guni[compraactual]->desc[ndesc],NULL,pantallamenu,&destino);
      }
      if(gui[uigui][i]->nmensajes() == 0)
      {
       destino.x = 640 - UP[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->w;
       destino.y = 480 - UP[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->h;
       destino.w = UP[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->w;
       destino.h = UP[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->h;
       SDL_BlitSurface(UP[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id],NULL,pantallamenu,&destino);
      }
      else
      {
       destino.x = 640 - UI[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->w;
       destino.y = 480 - UI[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->h;
       destino.w = UI[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->w;
       destino.h = UI[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id]->h;
       SDL_BlitSurface(UI[nucleo->unidades(gui[uigui][i]->nmensajes())[compra[compraactual]].id],NULL,pantallamenu,&destino);
      }
      destino.x = gui[uigui][i]->x()+510;
      destino.y = gui[uigui][i]->y()+9;
      destino.w = imagen[7]->w;
      destino.h = imagen[7]->h;
      SDL_BlitSurface(imagen[7],NULL,pantallamenu,&destino);
      destino.x = gui[uigui][i]->x()+10;
      destino.y = gui[uigui][i]->y()+250;
      destino.w = dinero->w;
      destino.h = dinero->h;
      SDL_BlitSurface(dinero,NULL,pantallamenu,&destino);
     }
    } break;
    case G_T_LMAPAS:
    {
     SDL_Rect destino;
     destino.x = gui[uigui][i]->x();
     destino.y = gui[uigui][i]->y();
     destino.w = imagen[4]->w;
     destino.h = imagen[4]->h;
     SDL_BlitSurface(imagen[4],NULL,pantallamenu,&destino);
     destino.x = gui[uigui][i]->x() + 565;
     destino.y = gui[uigui][i]->y() + 5;
     destino.w = imagen[25]->w;
     destino.h = imagen[25]->h;
     SDL_BlitSurface(imagen[25],NULL,pantallamenu,&destino);
     destino.y += 260;
     SDL_BlitSurface(imagen[26],NULL,pantallamenu,&destino);
     destino.x = gui[uigui][i]->x() + 8;
     destino.y = gui[uigui][i]->y() + 8;
     destino.h = 37;
     unsigned int TOTAL = nucleo->num_maps();
     unsigned int PRIMERO = (int)gui[uigui][i]->g_texto[1];
     unsigned int ELEGIDO = (int)gui[uigui][i]->g_texto[0];
     for(unsigned int r = PRIMERO;r < min(PRIMERO + 7,TOTAL);r++)
     {
      if(ELEGIDO == r)
      {
       destino.w = 555;
       SDL_BlitSurface(imagen[27],NULL,pantallamenu,&destino);
      }
      destino.w = texto_mapas[r]->w;
      SDL_BlitSurface(texto_mapas[r],NULL,pantallamenu,&destino);
      destino.y += 40;
     }
    } break;
   }
  }
}

/*******************************************************************************
/
/ método elegirmapas
/
/ Cambia al menú de selección de mapas del modo batalla.
/
*******************************************************************************/

void c_svideo::elegirmapas()
{
 cambiargui(16);
}

/*******************************************************************************
/
/ método ataque_local
/
/ Dibuja el daño.
/
*******************************************************************************/

SDL_Surface * c_svideo::ataque_local(int idg_atacante,int idg_defensor)
{
 int dano = nucleo->ataque_local(idg_atacante,idg_defensor);
 if(dano)
 {
  char * dan;
  dan = enteroacadena(dano);
  SDL_Color colorfuente;
   colorfuente.r = 255; colorfuente.g = 255; colorfuente.b = 255;
  SDL_Surface * d;
  d = TTF_RenderText_Blended(fuente[0],dan,colorfuente);
  return d;
 }
 return NULL;
}

/*******************************************************************************
/
/ método movimiento_local
/
/ indica al núcleo un movimiento.
/
*******************************************************************************/

void c_svideo::movimiento_local(int idg,int x,int y,int movrestante)
{
 nucleo->movimiento_local(idg,x,y,movrestante);
}

/*******************************************************************************
/
/ método movimiento_remoto
/
/ indica al tablero un movimiento.
/
*******************************************************************************/

void c_svideo::movimiento_remoto(int idg,int x,int y)
{
 tablero.movimiento_remoto(idg,x,y);
}

/*******************************************************************************
/
/ método ataque_remoto
/
/ Dibuja el daño.
/
*******************************************************************************/

void c_svideo::ataque_remoto(int idg,int dano)
{
 SDL_Surface * d = NULL;
 char * dan;
 dan = enteroacadena(dano);
 SDL_Color colorfuente;
 colorfuente.r = 255; colorfuente.g = 255; colorfuente.b = 255;
 d = TTF_RenderText_Blended(fuente[0],dan,colorfuente);

 tablero.ataque_remoto(idg,d);
 delete dan;
}

/*******************************************************************************
/
/ método eliminar_unidad_local
/
/ indica al tablero que elimine una unidad.
/
*******************************************************************************/

void c_svideo::elimina_unidad_local(int idg)
{
 tablero.elimina_unidad_local(idg);
}

/*******************************************************************************
/
/ método elimina_unidad_remota
/
/ indica al tablero que elimine una unidad.
/
*******************************************************************************/

void c_svideo::elimina_unidad_remota(int idg)
{
 tablero.elimina_unidad_remota(idg);
}

/*******************************************************************************
/
/ método restaurar_movimiento
/
/ indica al tablero que restaure el movimiento de las unidades (para iniciar
/ un nuevo turno).
/
*******************************************************************************/

void c_svideo::restaurar_movimiento()
{
 tablero.restaurar_movimiento();
}

/*******************************************************************************
/
/ método ciclo
/
/ Dibuja un frame.
/
/ Dibujará menús y batallas.
/
*******************************************************************************/

void c_svideo::ciclo()
{
 // Primero leo la cola de mensajes para ver si hay alguna acción que hacer.
 // Los decodifico y realizo las acciones que supongan cada uno.
 while(!mensajes.empty())
 {
  c_sv_mensaje msg;
  msg = mensajes.front();
  mensajes.pop();
  switch(msg.mensaje)
  {
   case G_CGUI:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_CGUI" << endl;
    cambiargui(msg.parametros[0]);
   } break;
   case G_CONECTAR:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_CONECTAR" << endl;
    nucleo->cliente();
    sred->cliente(gui[uigui][msg.parametros[0]]->texto());
    //nucleo->envia_puntuacion();
   } break;
   case G_SERVIR:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_SERVIR" << endl;
    nucleo->server();
    sred->servidor();
   } break;
   case G_CCUR:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_CCUR" << endl;
    ncursor=msg.parametros[0];
   } break;
   case G_CEJERCITO:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_CEJERCITO" << endl;
    nucleo->elige_ejercito(msg.parametros[0]);
   } break;
   case G_NMAPA:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_NMAPA" << endl;
    mapa.destruir();
   } break;
   case G_NANCHO:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_NANCHO" << endl;
    int ancho = 0;
    for(unsigned int i = 0;i < nogui[uigui];i++)
    {
     if(gui[uigui][i]->id() == msg.parametros[0])
     {
      ancho = cadenaaentero(gui[uigui][i]->texto());
      if(!ancho)
       ancho = 20;
      else
       ancho = min(103,ancho);
      i = nogui[uigui];
     }
    }
    mapa.ancho(ancho);
   } break;
   case G_NALTO:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_NALTO" << endl;
    int alto = 0;
    for(unsigned int i = 0;i < nogui[uigui];i++)
    {
     if(gui[uigui][i]->id() == msg.parametros[0])
     {
      alto = cadenaaentero(gui[uigui][i]->texto());
      if(!alto)
       alto = 20;
      else
       alto = min(70,alto);
      i = nogui[uigui];
     }
    }
    mapa.alto(alto);
   } break;
   case G_NNOMBRE:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_NNOMBRE" << endl;
    for(unsigned int i = 0;i < nogui[uigui];i++)
    {
     if(gui[uigui][i]->id() == msg.parametros[0])
     {
      char nombre[101];
      strcpy(nombre,"./mapas/");
      strcat(nombre,gui[uigui][i]->texto());
      strcat(nombre,".tlrmap");
      for(unsigned int rec = 0;nombre[rec] != '\000';rec++)
       if(nombre[rec] == ' ') nombre[rec] = '_';
      mapa.nombrefichero(nombre);
      i = nogui[uigui];
     }
    }
   } break;
   case G_REGEN:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_REGEN" << endl;
    mapa.regenerar();
   } break;
   case G_TAB_MAPA:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_TAB_MAPA" << endl;
    tablero.asociar_mapa(mapa);
   } break;
   case G_CMODOB:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_CMODOB" << endl;
    FLAGS = FLAGS & ~OF_MODO_MENU;
   } break;
   case G_CMODOE:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_CMODOE" << endl;
    FLAGS = FLAGS | OF_MODO_EDICION;
    ssonido->pausa();
    tablero.hmodoedicion();
   } break;
   case G_QMODOE:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_QMODOE" << endl;
    FLAGS = FLAGS & ~OF_MODO_EDICION;
    ssonido->continuar();
   } break;
   case G_QMODOB:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_QMODOB" << endl;
    FLAGS = FLAGS | OF_MODO_MENU;
   } break;
   case G_EMAPA:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_EMAPA" << endl;
    mapa = nucleo->mapa(MD5[gui[uigui][msg.parametros[0]]->g_texto[0]+gui[uigui][msg.parametros[0]]->g_texto[1]]);
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Asociando mapa:" << mapa.ancho() << " " << mapa.alto() << endl;
    tablero.asociar_mapa(mapa);
    FLAGS = FLAGS | OF_MAPA_EDITADO;
   } break;
   case G_EMAPA_A:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_EMAPA_A" << endl;
    nucleo->mapa_aleatorio();
   } break;
   case G_EMAPA_S:
   {
    if(_M_G_DEBUG_)
     cout << "[svideo]-> Ejecutando instrucción G_EMAPA_S" << endl;
    nucleo->mapa_elegido(MD5[gui[uigui][msg.parametros[0]]->g_texto[0]+gui[uigui][msg.parametros[0]]->g_texto[1]]);
   } break;
  }
 }
 
 // Si está activo el modo menú, dibujo cada uno de los objetos del menú.
 if((FLAGS & OF_MODO_MENU))
 {
  SDL_Rect destino;
  destino.x = 0;
  destino.y = 0;
  destino.w = 640;
  destino.h = 480;
  SDL_BlitSurface(pantallamenu,NULL,pantalla,&destino);
 }
 else // Si estamos en modo batalla...
 {
  //////////////////////////
  ///// DIBUJO DE MAPA /////
  //////////////////////////
  if(FLAGS & OF_FIN_BATALLA)
  {
   SDL_Rect destino;
   destino.x = 0;
   destino.y = 0;
   destino.h = 480;
   destino.w = 640;
   SDL_BlitSurface(imagen[resultado],NULL,pantalla,&destino);
  }
  else
  {
  if(!(FLAGS & OF_ESCRITURA) && !(FLAGS & OF_MINIMAPA)) // Si el modo escritura no está activo y no estoy viendo el minimapa...
  { // Compruebo si hay movimientos y los realizo.
   if(nucleo->mx() > 620)
    tablero.moverse(0);
   if(nucleo->mx() < 20)
    tablero.moverse(1);
   if(nucleo->my() > 460)
    tablero.moverse(2);
   if(nucleo->my() < 20)
    tablero.moverse(3);
  }
  if(!(FLAGS & OF_ESCRITURA))
  { // Recorro la pantalla dibujando el trozo de cada tile que me haga falta.
   if(FLAGS & OF_DIBUJANDO)
    tablero.pintar(nucleo->mx(),nucleo->my());
   SDL_Rect destino;
   destino.x = 0;
   destino.y = 0;
   destino.w = 640;
   destino.h = 440;
   SDL_BlitSurface(tablero.tablero(),&(tablero.recorte()),pantalla,&destino);
  }
  else // Si estoy en modo escritura.
  { // Dibujo la ventana de diálogo.
   SDL_Rect destino;
   destino.x = 0;
   destino.y = 0;
   destino.w = 640;
   destino.h = 440;
   SDL_BlitSurface(imagen[12],NULL,pantalla,&destino);
   destino.x = 580;
   destino.y = 372;
   destino.w = 50;
   destino.h = 30;
   SDL_BlitSurface(imagen[13],NULL,pantalla,&destino);
   if(strlen(ndialogo))
   { // Dibujo el texto.
    destino.x = 5;
    destino.y = 400;
    destino.w = Sndialogo->w;
    destino.h = Sndialogo->h;
    SDL_BlitSurface(Sndialogo,NULL,pantalla,&destino);
   }
   list<SDL_Surface*>::iterator principio,final;
   final = dialogo.end();
   int py = 1;
   for(principio = dialogo.begin();principio!=final;principio++)
   { // Dibujo el histórico.
    destino.x = 5;
    destino.y = py;
    destino.w = (*principio)->w;
    destino.h = (*principio)->h;
    SDL_BlitSurface((*principio),NULL,pantalla,&destino);
    py+=37;
   }
  }

  // Dibujo la barra horizontal.
  SDL_Rect destino;
  destino.x = 0;
  destino.y = 440;
  destino.w = 640;
  destino.h = 40;
  SDL_BlitSurface(imagen[8],NULL,pantalla,&destino);
  if(FLAGS & OF_VIDA)
  {
   destino.x = 180;
   destino.y = 445;
   destino.w = vvida->w;
   destino.h = vvida->h;
   SDL_BlitSurface(vvida,NULL,pantalla,&destino);
  }
  if(FLAGS & OF_MINIMAPA)
  {
   destino.x = 0;
   destino.y = 0;
   destino.w = 640;
   destino.h = 440;
   SDL_BlitSurface(tablero.dminimapa(),NULL,pantalla,&destino);
  }
   destino.x = 120;
   destino.y = 445;
   destino.w = 50;
   destino.h = 30;
   SDL_BlitSurface(imagen[17],NULL,pantalla,&destino);
  if(FLAGS & OF_MODO_EDICION)
  {
   destino.x = 10;
   destino.y = 445;
   destino.w = 100;
   destino.h = 30;
   SDL_BlitSurface(imagen[18],NULL,pantalla,&destino);
   destino.x = 180;
   destino.y = 445;
   destino.w = 82;
   destino.h = 30;
   SDL_BlitSurface(imagen[19],NULL,pantalla,&destino);
   destino.x = 272;
   destino.y = 445;
   destino.w = 82;
   destino.h = 30;
   SDL_BlitSurface(imagen[20],NULL,pantalla,&destino);
   destino.x = 364;
   destino.y = 445;
   destino.w = 82;
   destino.h = 30;
   SDL_BlitSurface(imagen[21],NULL,pantalla,&destino);
   destino.x = 456;
   destino.y = 445;
   destino.w = 82;
   destino.h = 30;
   SDL_BlitSurface(imagen[22],NULL,pantalla,&destino);
   destino.x = 548;
   destino.y = 445;
   destino.w = 40;
   destino.h = 30;
   SDL_BlitSurface(imagen[23],NULL,pantalla,&destino);
   destino.x = 590;
   destino.y = 445;
   destino.w = 40;
   destino.h = 30;
   SDL_BlitSurface(imagen[24],NULL,pantalla,&destino);
  }
  else
  {
   if(FLAGS & OF_NUEVO_MENS)
   {
    if(contador_n_mensaje > 40)
    {
     destino.x = 580;
     destino.y = 445;
     destino.w = 50;
     destino.h = 30;
     SDL_BlitSurface(imagen[11],NULL,pantalla,&destino);
    }
    else
    {
     destino.x = 580;
     destino.y = 445;
     destino.w = 50;
     destino.h = 30;
     SDL_BlitSurface(imagen[28],NULL,pantalla,&destino);
    }
    contador_n_mensaje--;
    if(!contador_n_mensaje)
     contador_n_mensaje = 80;
   }
   else
   {
    destino.x = 580;
    destino.y = 445;
    destino.w = 50;
    destino.h = 30;
    SDL_BlitSurface(imagen[11],NULL,pantalla,&destino);
   }
   //////
   ////// Aquí dibujar fin turno.
   //////
   if(nucleo->devuelve_turno())
   {
    destino.x = 10;
    destino.y = 445;
    destino.w = 100;
    destino.h = 30;
    SDL_BlitSurface(imagen[15],NULL,pantalla,&destino);
    destino.x = 510;
    destino.y = 445;
    destino.w = 50;
    destino.h = 30;
    SDL_BlitSurface(imagen[29],NULL,pantalla,&destino);
   }
   else
   {
    destino.x = 10;
    destino.y = 445;
    destino.w = 100;
    destino.h = 30;
    SDL_BlitSurface(imagen[16],NULL,pantalla,&destino);
   }
  }
  }
 }
  // Dibujo el cursor.
 SDL_Rect destino;
 destino.x = nucleo->mx();
 destino.y = nucleo->my();
 destino.w = cursor[ncursor]->w;
 destino.h = cursor[ncursor]->h;
 SDL_BlitSurface(cursor[ncursor],NULL,pantalla,&destino);

 // Refresco la pantalla.
 SDL_Flip(pantalla);
}

/*******************************************************************************
/
/ método vida
/
/ Dibuja la vida de la unidad seleccionada.
/
*******************************************************************************/

void c_svideo::vida(unsigned int idg,unsigned int t)
{
 char * c;
 int ivida = nucleo->vida(idg,t);
 c = enteroacadena(ivida);
 cout << "[svideo]-> VIDA QUE LE QUEDA: " << c << endl;
 if(vvida)
  SDL_FreeSurface(vvida);
 SDL_Color colorfuente;
 colorfuente.r = 255; colorfuente.g = 255; colorfuente.b = 255;
 vvida = TTF_RenderText_Blended(fuente[0],c,colorfuente);
 FLAGS = FLAGS | OF_VIDA;
 delete c;
}

/*******************************************************************************
/
/ método cambiomenus
/
/ Cambia al modo menú
/
*******************************************************************************/

void c_svideo::cambiomenus()
{
 FLAGS = FLAGS | OF_MODO_MENU;
}

/*******************************************************************************
/
/ método cambiojuego
/
/ Cambio al modo batalla.
/
*******************************************************************************/

void c_svideo::cambiojuego()
{
 FLAGS = FLAGS & ~OF_MODO_MENU;
 FLAGS = FLAGS & ~OF_MODO_EDICION;
 tablero.dmodoedicion();
}

